package com.jim.healio.graphrag.service.impl;

import com.jim.healio.graphrag.model.MedicalEntity;
import com.jim.healio.graphrag.model.MedicalDocument;
import com.jim.healio.graphrag.model.DocumentSearchResult;
import com.jim.healio.graphrag.service.GraphRAGService;
import com.jim.healio.graphrag.service.Neo4jGraphService;
import com.jim.healio.graphrag.service.ChromaDocumentService;
import com.jim.healio.graphrag.service.SimplifiedDocumentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

/**
 * 真实的GraphRAG服务实现
 * 集成Neo4j图数据库和Chroma向量存储
 */
@Service
@Primary
@ConditionalOnProperty(prefix = "healio.graphrag", name = "enabled", havingValue = "true")
public class RealGraphRAGServiceImpl implements GraphRAGService {
    
    private static final Logger logger = LoggerFactory.getLogger(RealGraphRAGServiceImpl.class);
    
    @Autowired
    private Neo4jGraphService neo4jService;
    
    @Autowired
    private ChromaDocumentService chromaService;
    
    @Autowired
    private SimplifiedDocumentService simplifiedDocumentService;
    
    @Autowired
    private MockGraphRAGServiceImpl mockService; // 作为备选方案
    
    @Override
    public List<MedicalEntity> queryEntities(String query) {
        logger.info("GraphRAG查询医学实体: {}", query);
        
        // 优先使用Neo4j图数据库查询
        if (neo4jService.isNeo4jAvailable()) {
            try {
                List<MedicalEntity> entities = neo4jService.queryEntities(query);
                if (!entities.isEmpty()) {
                    logger.info("从Neo4j查询到 {} 个实体", entities.size());
                    return entities;
                }
            } catch (Exception e) {
                logger.warn("Neo4j查询失败，回退到模拟数据: {}", e.getMessage());
            }
        }
        
        // 回退到模拟服务
        logger.info("使用模拟服务查询实体");
        return mockService.queryEntities(query);
    }
    
    @Override
    public List<DocumentSearchResult> semanticSearch(String query, int limit) {
        logger.info("GraphRAG语义搜索: {}, 限制: {}", query, limit);
        
        // 优先使用简化文档服务
        try {
            List<DocumentSearchResult> results = simplifiedDocumentService.semanticSearch(query, limit);
            if (!results.isEmpty()) {
                logger.info("从简化文档服务查询到 {} 个文档", results.size());
                return results;
            }
        } catch (Exception e) {
            logger.warn("简化文档服务查询失败: {}", e.getMessage());
        }
        
        // 回退到模拟服务
        logger.info("使用模拟服务进行语义搜索");
        return mockService.semanticSearch(query, limit);
    }
    
    @Override
    public List<DocumentSearchResult> hybridSearch(String query, List<String> entityIds, int limit) {
        logger.info("GraphRAG混合搜索: {}, 实体: {}, 限制: {}", query, entityIds, limit);
        
        List<DocumentSearchResult> results = new ArrayList<>();
        
        // 1. 首先通过图数据库查询相关实体，扩展实体列表
        List<String> expandedEntityIds = new ArrayList<>();
        if (entityIds != null) {
            expandedEntityIds.addAll(entityIds);
        }
        
        if (neo4jService.isNeo4jAvailable()) {
            try {
                List<MedicalEntity> queryEntities = neo4jService.queryEntities(query);
                expandedEntityIds.addAll(
                    queryEntities.stream()
                        .map(MedicalEntity::getId)
                        .collect(Collectors.toList())
                );
            } catch (Exception e) {
                logger.warn("图查询扩展实体失败: {}", e.getMessage());
            }
        }
        
        // 2. 使用简化文档服务进行混合搜索
        try {
            results = simplifiedDocumentService.hybridSearch(query, expandedEntityIds, limit);
            if (!results.isEmpty()) {
                logger.info("混合搜索找到 {} 个文档", results.size());
                return results;
            }
        } catch (Exception e) {
            logger.warn("简化文档服务混合搜索失败: {}", e.getMessage());
        }
        
        // 回退到模拟服务
        logger.info("使用模拟服务进行混合搜索");
        return mockService.hybridSearch(query, entityIds, limit);
    }
    
    @Override
    public List<DocumentSearchResult> queryDocumentsByEntity(String entityId, int limit) {
        logger.info("GraphRAG根据实体查询文档: {}, 限制: {}", entityId, limit);
        
        // 使用简化文档服务查询
        try {
            List<DocumentSearchResult> results = simplifiedDocumentService.queryDocumentsByEntity(entityId, limit);
            if (!results.isEmpty()) {
                logger.info("根据实体查询到 {} 个文档", results.size());
                return results;
            }
        } catch (Exception e) {
            logger.warn("简化文档服务实体查询失败: {}", e.getMessage());
        }
        
        // 回退到模拟服务
        return mockService.queryDocumentsByEntity(entityId, limit);
    }
    
    @Override
    public List<MedicalEntity> analyzeSymptomRelations(List<String> symptoms) {
        logger.info("GraphRAG症状关联分析: {}", symptoms);
        
        // 使用Neo4j进行图查询分析
        if (neo4jService.isNeo4jAvailable()) {
            try {
                List<MedicalEntity> entities = neo4jService.analyzeSymptomRelations(symptoms);
                if (!entities.isEmpty()) {
                    logger.info("症状关联分析找到 {} 个相关实体", entities.size());
                    return entities;
                }
            } catch (Exception e) {
                logger.warn("Neo4j症状关联分析失败: {}", e.getMessage());
            }
        }
        
        // 回退到模拟服务
        return mockService.analyzeSymptomRelations(symptoms);
    }
    
    @Override
    public List<MedicalEntity> queryDrugInteractions(List<String> drugs) {
        logger.info("GraphRAG药物相互作用查询: {}", drugs);
        
        // 使用Neo4j查询药物相互作用
        if (neo4jService.isNeo4jAvailable()) {
            try {
                List<MedicalEntity> interactions = neo4jService.queryDrugInteractions(drugs);
                if (!interactions.isEmpty()) {
                    logger.info("药物相互作用查询找到 {} 个相互作用", interactions.size());
                    return interactions;
                }
            } catch (Exception e) {
                logger.warn("Neo4j药物相互作用查询失败: {}", e.getMessage());
            }
        }
        
        // 回退到模拟服务
        return mockService.queryDrugInteractions(drugs);
    }
    
    @Override
    public List<DocumentSearchResult> getTreatmentGuidelines(String condition) {
        logger.info("GraphRAG获取治疗指南: {}", condition);
        
        // 构建治疗指南查询
        String guidelineQuery = condition + " 治疗指南 临床指南";
        
        // 使用向量搜索查找相关指南
        List<DocumentSearchResult> results = semanticSearch(guidelineQuery, 5);
        
        // 过滤只返回指南类型的文档
        List<DocumentSearchResult> guidelines = results.stream()
            .filter(result -> {
                if (result.getMetadata() == null) return true;
                String type = (String) result.getMetadata().get("type");
                return type == null || type.equals("GUIDELINE") || 
                       result.getTitle().contains("指南") || result.getTitle().contains("guideline");
            })
            .collect(Collectors.toList());
        
        logger.info("治疗指南查询找到 {} 个指南", guidelines.size());
        return guidelines;
    }
    
    @Override
    public void storeDocument(MedicalDocument document) {
        logger.info("GraphRAG存储文档: {}", document.getTitle());
        
        // 同时存储到文档服务和建立图关联
        try {
            // 存储到简化文档服务
            simplifiedDocumentService.storeDocument(document);
            
            // 在Neo4j中建立实体-文档关联
            if (neo4jService.isNeo4jAvailable()) {
                for (String entityId : document.getExtractedEntityIds()) {
                    neo4jService.addEntityDocumentLink(entityId, document.getId());
                }
            }
            
            logger.info("文档存储成功: {}", document.getTitle());
            
        } catch (Exception e) {
            logger.error("文档存储失败: " + document.getTitle(), e);
            throw new RuntimeException("文档存储失败", e);
        }
    }
    
    @Override
    public void storeEntity(MedicalEntity entity) {
        logger.info("GraphRAG存储实体: {}", entity.getName());
        
        // 存储到Neo4j图数据库
        if (neo4jService.isNeo4jAvailable()) {
            try {
                neo4jService.storeEntity(entity);
                logger.info("实体存储成功: {}", entity.getName());
            } catch (Exception e) {
                logger.error("实体存储失败: " + entity.getName(), e);
                throw new RuntimeException("实体存储失败", e);
            }
        } else {
            logger.warn("Neo4j未配置，实体存储被跳过: {}", entity.getName());
        }
    }
    
    /**
     * 批量存储文档
     */
    public void storeDocuments(List<MedicalDocument> documents) {
        logger.info("GraphRAG批量存储 {} 个文档", documents.size());
        
        try {
            // 批量存储到简化文档服务
            simplifiedDocumentService.storeDocuments(documents);
            
            // 批量建立Neo4j关联
            if (neo4jService.isNeo4jAvailable()) {
                for (MedicalDocument doc : documents) {
                    for (String entityId : doc.getExtractedEntityIds()) {
                        neo4jService.addEntityDocumentLink(entityId, doc.getId());
                    }
                }
            }
            
            logger.info("批量文档存储成功");
            
        } catch (Exception e) {
            logger.error("批量文档存储失败", e);
            throw new RuntimeException("批量文档存储失败", e);
        }
    }
    
    /**
     * 批量存储实体
     */
    public void storeEntities(List<MedicalEntity> entities) {
        logger.info("GraphRAG批量存储 {} 个实体", entities.size());
        
        if (neo4jService.isNeo4jAvailable()) {
            try {
                for (MedicalEntity entity : entities) {
                    neo4jService.storeEntity(entity);
                }
                logger.info("批量实体存储成功");
            } catch (Exception e) {
                logger.error("批量实体存储失败", e);
                throw new RuntimeException("批量实体存储失败", e);
            }
        } else {
            logger.warn("Neo4j未配置，批量实体存储被跳过");
        }
    }
    
    /**
     * 初始化GraphRAG系统
     */
    public void initializeGraphRAG() {
        logger.info("初始化GraphRAG系统...");
        
        try {
            // 初始化Neo4j数据库结构
            if (neo4jService.isNeo4jAvailable()) {
                neo4jService.initializeDatabase();
                neo4jService.createBasicMedicalRelationships();
            }
            
            logger.info("GraphRAG系统初始化完成");
            
        } catch (Exception e) {
            logger.error("GraphRAG系统初始化失败", e);
        }
    }
    
    /**
     * 获取系统状态
     */
    public String getSystemStatus() {
        StringBuilder status = new StringBuilder();
        status.append("GraphRAG系统状态:\n");
        status.append("- Neo4j图数据库: ").append(neo4jService.isNeo4jAvailable() ? "可用" : "不可用").append("\n");
        status.append("- 简化文档服务: ").append(simplifiedDocumentService.isAvailable() ? "可用" : "不可用").append("\n");
        status.append("- 文档数量: ").append(simplifiedDocumentService.getDocumentCount()).append("\n");
        
        if (!neo4jService.isNeo4jAvailable()) {
            status.append("- 图数据使用模拟服务");
        }
        
        return status.toString();
    }
} 